home *** CD-ROM | disk | FTP | other *** search
- /* Copyright ) Darin Johnson, 1989 */
- /* */
- /* Permission is granted to use */
- /* this program and to freely copy */
- /* it and/or source code as long */
- /* as these notices remain. */
- /* No charges for these copies may */
- /* be made, except for handling */
- /* and distribution fees. */
-
- /* This program puts customized menus into the WorkBench menubar. */
- /* The program is split up into two parts, MyMenu and MyMenu-Handler. */
- /* This section is MyMenu and it initializes and starts up a process */
- /* to run MyMenu-Handler, and then terminates. MyMenu also terminates */
- /* and cleans up after the suprocess. MyMenu will parse the users */
- /* menus, initialize data to be passed to MyMenu-Handler, and start */
- /* up MyMenu-Handler. MyMenu-Handler does very little memory */
- /* allocation in order to save space, so MyMenu does allocation and */
- /* freeing for it. */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <graphics/gfxbase.h>
- #include <intuition/intuitionbase.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <functions.h>
- #include <stdio.h>
- #include <ctype.h>
- #include "mymenu.h"
-
- static char *copyright = "Copyright ) Darin Johnson, 1989";
-
- /* actually, I don't know if it will work under Lattice */
- #ifdef AZTEC_C
- #define strcmp _BUILTIN_strcmp
- #define strcpy _BUILTIN_strcpy
- #define strlen _BUILTIN_strlen
- #endif
-
- struct IntuitionBase *IntuitionBase = NULL;
- struct GfxBase *GfxBase = NULL;
-
- extern int menu_num;
-
- /* this is the data structure that we use to pass data to MyMenu-Handler */
- struct MMData *MM;
-
- char do_quit;
- int i;
-
- /* make (and allocate) a copy of the passed string */
- char *copystr(str)
- char *str;
- {
- char *newstr;
- newstr = AllocMem(strlen(str)+1, MEMF_PUBLIC);
- strcpy(newstr, str);
- return newstr;
- }
-
- /* strcmp, ignoring case */
- #define UPPER(c) (islower(c)?toupper(c):(c))
- int stricmp(s, t)
- char *s, *t;
- {
- for ( ; UPPER(*s) == UPPER(*t); s++, t++)
- if (*s== NULL)
- return 0;
- return UPPER(*s) - UPPER(*t);
- }
-
- /* Find the workbench window - I'm sure there's a better way... */
- struct Window *find_workbench() {
- struct Screen *scr;
- struct Window *win;
- ULONG ilock;
- ilock = LockIBase(0L); /* just so's things don't change on us */
- for (scr = IntuitionBase->FirstScreen; /* find WB Screen */
- scr && strcmp(scr->DefaultTitle, "Workbench Screen");
- scr=scr->NextScreen);
- if (!scr) {
- UnlockIBase(ilock);
- printf("That's odd... I can't find the workbench screen...\n");
- _abort(2000);
- }
- for (win=scr->FirstWindow; win; win = win->NextWindow)
- if (win->Flags & WBENCHWINDOW) break;
- UnlockIBase(ilock);
- return win;
- }
-
- /* open a library */
- APTR *open_lib(name, rev)
- char *name;
- long rev;
- {
- APTR *lib;
- if ((lib = (APTR*)OpenLibrary(name, rev)) == NULL) {
- printf("Can't open %s (rev=%d\n", name, rev);
- _abort(1000);
- }
- return lib;
- }
-
- /* make a copy of our CLI path. We also convert BCPL stuff. */
- copy_path() {
- register struct Path *oldpath, *newpath, *tmppath;
- struct CommandLineInterface *cli;
- struct Process *pr;
-
- pr = (struct Process *)FindTask(NULL);
- cli = (struct CommandLineInterface *)BADDR(pr->pr_CLI);
- newpath = MM->CLI_path = NULL;
- for (oldpath = (struct Path *)BADDR(cli->cli_CommandDir); oldpath;
- oldpath = (struct Path *) BADDR(oldpath->path_Next)) {
- tmppath = (struct Path *)AllocMem(sizeof(struct Path), MEMF_PUBLIC);
- if (!MM->CLI_path) {
- MM->CLI_path = tmppath;
- } else {
- newpath->path_Next = tmppath; /* we don't convert to BCPL */
- }
- newpath = tmppath;
- tmppath->path_Next = NULL;
- tmppath->path_Lock = DupLock(oldpath->path_Lock);
- }
- }
-
- /* free up the space used by the copy of the CLI path */
- free_path() {
- register struct Path *tmp, *path;
- /* clean out copy of path */
- path = MM->CLI_path;
- MM->CLI_path = NULL;
- while (path) {
- tmp = path;
- path = path->path_Next;
- UnLock(tmp->path_Lock);
- FreeMem(tmp, sizeof(struct Path));
- }
- }
-
- /* Initialize and load up the handler process, or update the menus */
- /* for an existing handler. */
- add_handler() {
- ULONG ilock;
-
- if (MM) {
- /* remove old menus and update */
- printf("Updating menus -- ");
- fflush(stdout);
- /* coordinate with handler */
- MM->parent_task = FindTask(NULL);
- MM->parent_sig = AllocSignal(-1L);
- Signal(MM->handler_task, SIGBREAKF_CTRL_D);
- Wait(1 << MM->parent_sig);
- /* clean old stuff up */
- free_menus();
- ilock = LockIBase(0L);
- menu_num = 0;
- for (MM->prev_menu = MM->WBWindow->MenuStrip;
- MM->prev_menu->NextMenu;
- MM->prev_menu=MM->prev_menu->NextMenu)
- menu_num++;
- UnlockIBase(ilock);
-
- /* get new menus */
- if (!parse_menus()) {
- do_quit = TRUE;
- return;
- }
-
- /* let handler know it can continue */
- Signal(MM->handler_task, SIGBREAKF_CTRL_D);
- printf("ok\n");
- return;
- }
-
- /* create a new handler */
- printf("Installing MyMenu -- ");
- fflush(stdout);
-
- /* get area to pass data in */
- MM = (struct MMData *)AllocMem(sizeof(struct MMData), MEMF_PUBLIC|MEMF_CLEAR);
-
- MM->WBWindow = find_workbench();
- if (MM->WBWindow==NULL) {
- printf("Can't find Workbench...\n");
- do_quit = TRUE;
- return;
- }
-
- /* we need to find out what menu number ours start at */
- ilock = LockIBase(0L);
- menu_num = 0;
- for (MM->prev_menu = MM->WBWindow->MenuStrip;
- MM->prev_menu->NextMenu;
- MM->prev_menu=MM->prev_menu->NextMenu)
- menu_num++;
- UnlockIBase(ilock);
-
- /* read in user's menus */
- if (!parse_menus()) {
- do_quit = TRUE;
- return;
- }
-
- MM->port.mp_Flags = PA_IGNORE; /* we'll get msg's from do_wbrun */
- MM->port.mp_Node.ln_Pri = 0;
- MM->port.mp_Node.ln_Type = NT_MSGPORT;
- MM->port.mp_Node.ln_Name = copystr(MYMENU_NAME);
- NewList(&MM->port.mp_MsgList);
-
- /* load in handler */
- MM->segment = LoadSeg("l:MyMenu-Handler");
- if (!MM->segment)
- MM->segment = LoadSeg("MyMenu-Handler");
- if (!MM->segment) {
- printf("Can't find L:MyMenu-Handler\n");
- do_quit = TRUE;
- return;
- }
-
- /* add to port list so that handler can find it */
- AddPort(&MM->port);
-
- MM->parent_task = FindTask(NULL);
- MM->parent_sig = AllocSignal(-1L);
- copy_path();
- CreateProc(MYMENU_NAME, 0, MM->segment, STACK);
- /* handshake so that we know it got started ok */
- Wait(1 << MM->parent_sig);
- FreeSignal(MM->parent_sig);
- if (MM->error_code) {
- printf("Handler error (%d)\n", MM->error_code);
- do_quit = TRUE;
- } else {
- printf("ok - %s\n", VERSION);
- }
- }
-
- /* shutdown and clean up after handler */
- remove_handler() {
- if (!MM)
- return;
- printf("removing -- ");
- fflush(stdout);
- if (MM->segment != NULL) {
- MM->parent_task = FindTask(NULL);
- MM->parent_sig = AllocSignal(-1L);
- Signal(MM->handler_task, SIGBREAKF_CTRL_C);
-
- /* wait until handler cleans up */
- /* (don't advertise that we catch ^C - for emergency use only) */
- Wait(1 << MM->parent_sig);
- FreeSignal(MM->parent_sig);
- if (MM->error_code != ERR_OK) {
- /* we can get an error if there are outstanding WB processes */
- printf("Leaving handler in place...\n");
- return;
- }
- RemPort(&MM->port);
- UnLoadSeg(MM->segment);
- }
- /* this is done here, not in handler... */
- free_path();
- free_menus();
- if (MM->port.mp_Node.ln_Name)
- FreeMem(MM->port.mp_Node.ln_Name, strlen(MM->port.mp_Node.ln_Name)+1);
- FreeMem(MM, sizeof(struct MMData));
- printf("done\n");
- }
-
- /* Close up libraries and exit. Having a routine named _abort() is */
- /* handy for use with SDB, otherwise, I would have a better name. */
- _abort(st)
- int st;
- {
- if (IntuitionBase)
- CloseLibrary(IntuitionBase);
- if (GfxBase)
- CloseLibrary(GfxBase);
- exit(st);
- }
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- IntuitionBase = (struct IntuitionBase *)open_lib("intuition.library", 0L);
- GfxBase = (struct GfxBase *)open_lib("graphics.library", 0L);
-
- do_quit=FALSE;
- for (i=1; i<argc; i++) {
- if (stricmp(argv[i], "QUIT")==0) {
- do_quit=TRUE;
- continue;
- }
- /* no other options yet */
- printf("Usage: MyMenu [quit]\n");
- _abort(10);
- }
-
- /* find shared data (if it exists) */
- MM = (struct MMData *)FindPort(MYMENU_NAME);
-
- if (do_quit == FALSE) {
- add_handler();
- };
- if (do_quit==TRUE) { /* note that this isn't an 'else' */
- remove_handler();
- }
- _abort(0);
- }
-